package cz.mzk.funnylib.dao.db;

import cz.mzk.funnylib.dao.UserDAO;
import cz.mzk.funnylib.entities.User;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;

/**
 *
 * @author xrosecky
 */
public class UserDAOImpl implements UserDAO {

    private static String ADD_USER = "INSERT INTO users(name, surname, login, password) VALUES(?, ?, ?, ?)";
    private static String UPDATE_USER = "UPDATE users SET name = ?, surname =?, login = ?, password = ? WHERE id = ?";
    private static String SELECT_USER_BY_ID = "SELECT id, name, surname, login, password FROM users WHERE id = ?";
    private static String SELECT_USER_BY_LOGIN = "SELECT id, name, surname, login, password FROM users WHERE login = ?";
    private static String SELECT_USERS = "SELECT id, name, surname, login, password FROM users";
    private JdbcTemplate jdbcTemplate;

    public UserDAOImpl(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public User getUserById(Long id) {
        return (User) jdbcTemplate.queryForObject(SELECT_USER_BY_ID, new Object[]{id}, new UserMapper());
    }

    public User getUserByLogin(String login) {
        return (User) jdbcTemplate.queryForObject(SELECT_USER_BY_LOGIN, new Object[]{login}, new UserMapper());
    }

    public List<User> getUsers() {
        return (List<User>) jdbcTemplate.query(SELECT_USERS, new UserMapper());
    }

    public void persist(final User user) {
        if (user.getId() == null) {
            GeneratedKeyHolder keyHolder = new GeneratedKeyHolder();
            try {
                jdbcTemplate.update(new PreparedStatementCreator() {

                    @Override
                    public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {
                        PreparedStatement preparedStatement = conn.prepareStatement(ADD_USER, Statement.RETURN_GENERATED_KEYS);
                        preparedStatement.setString(1, user.getName());
                        preparedStatement.setString(2, user.getSurname());
                        preparedStatement.setString(3, user.getLogin());
                        preparedStatement.setString(4, user.getPassword());
                        return preparedStatement;
                    }
                }, keyHolder);
            } catch (DataIntegrityViolationException ex) {
                throw new RuntimeException("User already exists!", ex);
            }
            user.setId(keyHolder.getKey().longValue());
        } else {
            jdbcTemplate.update(new PreparedStatementCreator() {

                @Override
                public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {
                    PreparedStatement preparedStatement = conn.prepareStatement(UPDATE_USER);
                    preparedStatement.setString(1, user.getName());
                    preparedStatement.setString(2, user.getSurname());
                    preparedStatement.setString(3, user.getLogin());
                    preparedStatement.setString(4, user.getPassword());
                    return preparedStatement;
                }
            });
        }
    }

    public class UserMapper implements RowMapper<User> {

        @Override
        public User mapRow(ResultSet rs, int rowNum) throws SQLException {
            User user = new User();
            user.setId(rs.getLong(1));
            user.setName(rs.getString(2));
            user.setSurname(rs.getString(3));
            user.setLogin(rs.getString(4));
            user.setPassword(rs.getString(5));
            return user;
        }
    }
}
